<?php
/**
 * Zend CMS 后台网站Session管理类
 * @author Administrator
 *
 */
class Cms_AdminSession {
	protected static $instance = false;
	
	private $session_info;
	private $session_db;
	private $session_model;
	
	/**
	 * 当前时间戳
	 */
	private $timestamp;
	
	/**
	 * 当前用户IP
	 */
	private $onlineip;
	private $onlineip_arr;
	private $sid;
	
	private $onlinetime_span;
	private $onlinetime_interval;
	private $onlinetime_max;
	
	private $clear_session_time;
	private $cookie_expiring_date;
	private $cookie_prefix;
	private $cookie_domain;
	private $cookie_path;
	
	//	const ONLINE_TIME_SPAN = 600;//10分钟,本设置用以设定更新用户在线时间的时间频率
	//	const CLEAR_SESSION_TIME = 2700;//30分钟,本设置用以设定用户自动登出时间
	//	const COOKIE_EXPIRING_DATE = 604800;//7天，本设置用以设定默认COOKIE保存时间
	

	private $secretKeyA = '9lZJ(dj{76a|N5^M3\":Tb@{nWi.;<H=m5<-$mT}TM2x+{nzxW/)eN8i`k9ra_1t%';
	private $secretKeyB = 'pyW0/9\"i^3bTs$oOYaD35r[HN*0\'{\"AsXbB@7O3)uD$H1\']e7L]7@VrAZl~X} ;%';
	public $secretKeyC = 'soOYaD3bB7OV';
	
	public static function getInstance() {
		if (! self::$instance) {
			self::$instance = new self ();
		}
		return self::$instance;
	}
	
	/**
	 * 构造函数
	 * 注册SID，Session信息入库
	 */
	public function init($cookie_config) {
		$this->timestamp = time ();
		if (getenv ( 'HTTP_CLIENT_IP' ) && strcasecmp ( getenv ( 'HTTP_CLIENT_IP' ), 'unknown' )) {
			$this->onlineip = getenv ( 'HTTP_CLIENT_IP' );
		} elseif (getenv ( 'HTTP_X_FORWARDED_FOR' ) && strcasecmp ( getenv ( 'HTTP_X_FORWARDED_FOR' ), 'unknown' )) {
			$this->onlineip = getenv ( 'HTTP_X_FORWARDED_FOR' );
		} elseif (getenv ( 'REMOTE_ADDR' ) && strcasecmp ( getenv ( 'REMOTE_ADDR' ), 'unknown' )) {
			$this->onlineip = getenv ( 'REMOTE_ADDR' );
		} elseif (isset ( $_SERVER ['REMOTE_ADDR'] ) && $_SERVER ['REMOTE_ADDR'] && strcasecmp ( $_SERVER ['REMOTE_ADDR'], 'unknown' )) {
			$this->onlineip = $_SERVER ['REMOTE_ADDR'];
		}
		$this->onlineip_arr = explode ( '.', $this->onlineip );
		
		$this->cookie_path = $cookie_config ['path'];
		$this->cookie_domain = $cookie_config ['domain'];
		$this->cookie_prefix = $cookie_config ['prefix'];
		$this->cookie_expiring_date = $cookie_config ['expiring_date'];
		$this->clear_session_time = $cookie_config ['clear_session_time'];
		$this->onlinetime_span = $cookie_config ['onlinetime_span'] ? $cookie_config ['onlinetime_span'] : 300;
		$this->onlinetime_interval = $cookie_config ['onlinetime_interval'] ? $cookie_config ['onlinetime_interval'] : 600;
		$this->onlinetime_max = $cookie_config ['onlinetime_interval'];
		
		$this->session_db = new DB_AdminSession ();
		//唯一客户端
		$this->sid = $this->getSid ();
		
		//初始化一些COOKIE信息
		$this->initCookie ();
		
		//检查cookie的合法性
		$this->checkCookieAuth ();
		
		//同步Session信息,clear/insert/update session
		$this->syncSession ();
		
		//执行网站扩展Seesion信息初始化操作,即注册常用信息到session
		$this->session_info ['onlineip'] = $this->onlineip;
		$this->session_info ['timestamp'] = $this->timestamp;
		
		Zend_Loader::loadClass ( 'Model_AdminSession' );
		$this->session_model = new Model_AdminSession ();
		$session_extinfo = $this->session_model->sessionExtInit ( $this->session_info );
		
		//此用户已经从数据库中删除，或者数据库异常
		if (isset ( $this->session_info ['uid'] ) && isset ( $session_extinfo ['user_info'] ['uid'] ) && $session_extinfo ['user_info'] ['uid'] == $this->session_info ['uid']) {
			
			$this->session_info ['user_info'] = $session_extinfo ['user_info'];
			if ($session_extinfo ['user_info'] ['username']) {
				$this->session_info ['username'] = $session_extinfo ['user_info'] ['username'];
			}
		} else {
			unset ( $this->session_info ['uid'] );
		
		//$this->clearcookies ();
		}
		$this->session_info ['site_info'] = $session_extinfo ['site_info'];
		if (Zend_Registry::isRegistered ( 'Smarty' )) {
			$_tpl = Zend_Registry::get ( 'Smarty' );
			$_tpl->assign ( 'AdminSessionInfo', $this->session_info );
		}
	}
	
	function __get($name) {
		if ($name == 'session_info') {
			return $this->$name;
		}
		return null;
	}
	
	/**
	 * 获取最新session信息
	 */
	private function syncSession() {
		//尝试从数据库中获取相关的Seesion信息
		$_session_info = $this->session_db->loadSessionInfoBySid ( $this->sid );
		
		//成功从表中读取到session信息
		if (isset ( $_session_info ['sid'] )) {
			$this->session_info ['lastactivity'] = $_session_info ['lastactivity'] ? $_session_info ['lastactivity'] : $this->timestamp;
			$this->session_info ['lastolupdate'] = $_session_info ['lastolupdate'] ? $_session_info ['lastolupdate'] : $this->timestamp;
			$this->session_info ['pageviews'] = $_session_info ['pageviews'];
			$this->session_info ['uid'] = $_session_info ['uid'];
			$this->session_info ['lang'] = $_session_info ['lang'];
			$this->session_info ['lock_screen'] = $_session_info ['lock_screen'];
			
			//更新Seesion表信息
			$this->updateSession ( $_session_info );
		
		//在线时长计算
		//$this->oltimeUpdate();
		} else {
			//表中没有seesion信息，将用户session入库
			

			//清除过期session
			$this->clearSession ();
			
			//插入新Session
			$this->insertSession ( $this->session_info );
		
		}
	}
	
	/**
	 * 初始话Cookie信息
	 */
	private function initCookie() {
		//记录此次Cookie的到期时间
		if (! isset ( $_COOKIE [$this->cookie_prefix . 'cookietime'] )) {
			$this->setcookie ( 'cookietime', $this->timestamp, $this->cookie_expiring_date, 1 );
		}
		
		//登陆的uid
		if (isset ( $_COOKIE [$this->cookie_prefix . 'uid'] )) {
			$this->session_info ['uid'] = $_COOKIE [$this->cookie_prefix . 'uid'];
		}
		
		//用户姓名
		if (isset ( $_COOKIE [$this->cookie_prefix . 'username_encode'] )) {
			$this->session_info ['username_encode'] = $_COOKIE [$this->cookie_prefix . 'username_encode'];
			$this->session_info ['username'] = urldecode ( $_COOKIE [$this->cookie_prefix . 'username_encode'] );
		}
	}
	
	/**
	 * 检查CookieAuth信息是否合法
	 */
	private function checkCookieAuth() {
		//cookie
		if (isset ( $_COOKIE [$this->cookie_prefix . 'authcode'] )) {
			$_authcode = $_COOKIE [$this->cookie_prefix . 'authcode'];
		} elseif (isset ( $_GET ['authcode'] )) {
			//GET方式传递认证码
			$_authcode = $_GET ['authcode'];
		}
		
		if (isset ( $_authcode )) {
			$_auth_memberinfo = encryption ( $_authcode, 'DECODE', $this->secretKeyA );
			$member_info_arr = explode ( ',', $_auth_memberinfo );
			$_auth_A2 = explode ( ',', $_auth_memberinfo );
			unset ( $_auth_A2 [count ( $_auth_A2 ) - 1] );
			$auth_A2 = implode ( ',', $_auth_A2 );
			if ($member_info_arr [count ( $member_info_arr ) - 1] == md5 ( $auth_A2 . $this->secretKeyB )) {
				
				$this->session_info ['uid'] = $member_info_arr [0];
				$this->session_info ['username'] = urldecode ( $member_info_arr [1] );
				$this->session_info ['username_encode'] = $member_info_arr [2];
				
				$this->setcookie ( 'uid', $this->session_info ['uid'], $this->cookie_expiring_date, 1 );
				
				//用户姓名
				if (! isset ( $_COOKIE [$this->cookie_prefix . 'username_encode'] )) {
					$this->setcookie ( 'username_encode', $this->session_info ['username_encode'], $this->cookie_expiring_date, 1 );
				}
				
				//登陆的uid
				if (! isset ( $_COOKIE [$this->cookie_prefix . 'uid'] )) {
					$this->setcookie ( 'uid', $this->session_info ['uid'], $this->cookie_expiring_date, 1 );
				}
				
				return true;
			}
		}
		
		return false;
	}
	
	/**
	 * 登陆认证，请求单点登陆服务器
	 */
	public function login($username, $password, $expiringdate = 0, &$login_rs = null) {
		$expiringdate && is_numeric ( $expiringdate ) ? $expiringdate = $this->cookie_expiring_date : $expiringdate = 0;
		$cms_config = Zend_Registry::get ( 'config' );
		//dump($cms_config['apisite']['opai']."/admin/login");exit();
		$c = curl_init ();
		curl_setopt ( $c, CURLOPT_URL, $cms_config->apisite->iapi . "/admin/login" );
		curl_setopt ( $c, CURLOPT_HEADER, 0 );
		curl_setopt ( $c, CURLOPT_POST, 1 );
		curl_setopt ( $c, CURLOPT_POSTFIELDS, "username={$username}&password={$password}&onlineip={$this->onlineip}" );
		curl_setopt ( $c, CURLOPT_RETURNTRANSFER, 1 );
		curl_setopt ( $c, CURLOPT_SSL_VERIFYPEER, FALSE );
		curl_setopt ( $c, CURLOPT_FOLLOWLOCATION, 0 );
		curl_setopt ( $c, CURLOPT_USERAGENT, $_SERVER ['HTTP_USER_AGENT'] );
		$login_info_xml = curl_exec ( $c );
		curl_close ( $c );
		//dump ( $login_info_xml );
		//exit ();
		$api = new Cms_Apidoc ();
		$lginfo_xml = $api->LoadXmlString ( $login_info_xml );
		$lginfo_response_status = $api->getXmlNodeAttribute ( $lginfo_xml->Response, 'status' );
		
		//dump($expiringdate);exit();
		$login_rs ['msg'] = $api->getXmlNodeValue ( $lginfo_xml->Response->Msg );
		//用户信息认证成功
		if ($lginfo_response_status == 'true') {
			
			$login_rs ['uid'] = $this->session_info ['uid'] = $api->getXmlNodeValue ( $lginfo_xml->Response->Resault->uid );
			$login_rs ['username'] = $this->session_info ['username'] = $api->getXmlNodeValue ( $lginfo_xml->Response->Resault->username );
			$login_rs ['lastlogintime'] = $this->session_info ['lastlogintime'] = $api->getXmlNodeValue ( $lginfo_xml->Response->Resault->lastlogintime );
			
			$this->setcookie ( 'authcode', $api->getXmlNodeValue ( $lginfo_xml->Response->Resault->authcode ), $expiringdate, 1 );
			
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * 加密Cookie
	 *
	 * @param array $userinfo
	 * @return string
	 */
	public function expatCookieAuth($userinfo) {
		
		$this->session_info ['uid'] = $userinfo ['uid'];
		$this->session_info ['username'] = $userinfo ['username'];
		$this->session_info ['username_encode'] = urlencode ( $userinfo ['username'] );
		
		$registry = Zend_Registry::getInstance ();
		$registry->set ( 'CmsAdminSessionInfo', $this->session_info );
		
		$_auth_memberinfo = $userinfo ['uid'] . "," . urlencode ( $userinfo ['username'] );
		return encryption ( $_auth_memberinfo . "," . md5 ( $_auth_memberinfo . $this->secretKeyB ), 'ENCODE', $this->secretKeyA );
	}
	
	/**
	 * 获取SID，生成SID
	 */
	private function getSid() {
		if (isset ( $_COOKIE [$this->cookie_prefix . 'sid'] )) {
			$this->session_info ['sid'] = $_COOKIE [$this->cookie_prefix . 'sid'];
			return $this->session_info ['sid'];
		} else {
			$this->session_info ['sid'] = random ( 6 );
			$_sid = $this->session_db->loadSessionInfoBySid ( $this->session_info ['sid'] );
			if ($_sid) {
				return $this->getSid ();
			}
			$this->setcookie ( 'sid', $this->session_info ['sid'], $this->cookie_expiring_date, 1 );
			return $this->session_info ['sid'];
		}
	}
	
	/**
	 * Session状态更新
	 */
	private function updateSession($_session_arr) {
		$supdate_row = array ("lastactivity" => $this->timestamp, "pageviews" => $_session_arr ['pageviews'] + 1 );
		
		//更新用户在线时长标志时间
		if (! $_session_arr ['lastolupdate']) {
			$supdate_row ['lastolupdate'] = $this->timestamp;
		}
		//		else if( $this->timestamp - $this->session_info['lastolupdate'] > $this->onlinetime_span ){
		//			$supdate_row['lastolupdate'] = $this->timestamp;
		//		}
		

		if (isset ( $this->session_info ['uid'] ) && $this->session_info ['uid']) {
			$supdate_row ['uid'] = $this->session_info ['uid'];
		} else {
			$supdate_row ['uid'] = 0;
		}
		
		if (isset ( $this->session_info ['username'] ) && $this->session_info ['username']) {
			$supdate_row ['username'] = $this->session_info ['username'];
		} else {
			$supdate_row ['username'] = 0;
		}
		
		$this->session_db->updateSessionInfoBySid ( $_session_arr ['sid'], $supdate_row );
	}
	
	/**
	 * 插入Session信息
	 */
	private function insertSession($_session_arr) {
		
		$new_session_arr = array ("sid" => $_session_arr ['sid'], "ip1" => $this->onlineip_arr [0], "ip2" => $this->onlineip_arr [1], "ip3" => $this->onlineip_arr [2], "ip4" => $this->onlineip_arr [3], "uid" => isset ( $_session_arr ['uid'] ) ? $_session_arr ['uid'] : 0, "username" => isset ( $_session_arr ['username'] ) ? $_session_arr ['username'] : 0, "lastactivity" => $this->timestamp, "lastolupdate" => $this->timestamp );
		
		$this->session_db->insertSessionInfo ( $new_session_arr );
	}
	
	/**
	 * 清理超时Session
	 */
	private function clearSession() {
		if (! isset ( $this->session_info ['uid'] )) {
			$this->session_info ['uid'] = 0;
		}
		$this->session_db->delete ( "
			(sid='" . $this->sid . "' OR lastactivity < " . ($this->timestamp - $this->clear_session_time) . ") 
			OR ('" . $this->session_info ['uid'] . "'<>'0' AND uid='" . $this->session_info ['uid'] . "')
			OR ( uid='0' AND ip1='" . $this->onlineip_arr [0] . "' AND ip2='" . $this->onlineip_arr [1] . "' 
			AND ip3='" . $this->onlineip_arr [2] . "' AND ip4='" . $this->onlineip_arr [3] . "' 
			AND lastactivity>" . ($this->timestamp - 60) . ")
			" );
	}
	
	/**
	 * 设置COOKIE
	 *
	 * @param string $var
	 * @param string $value
	 * @param int $life
	 * @param int $prefix
	 * @return true
	 */
	public function setcookie($var, $value, $life = 0, $prefix = 1) {
		setcookie ( ($prefix ? $this->cookie_prefix : '') . $var, $value, $life ? $this->timestamp + $life : 0, $this->cookie_path, $this->cookie_domain, $_SERVER ['SERVER_PORT'] == 443 ? 1 : 0 );
	}
	
	/**
	 * 清除网站COOKIE
	 */
	public function clearcookies() {
		//删除AdminSession表中登陆数据
		$DB_AdminSession = new DB_AdminSession ();
		$DB_AdminSession->updateSessionInfoBySid ( $this->sid, array ('uid' => 0, 'username' => 0 ) );
		
		$this->setcookie ( 'username_encode', null, - 86400 * 365, 1 );
		$this->setcookie ( 'uid', null, - 86400 * 365, 1 );
		$this->setcookie ( 'authcode', null, - 86400 * 365, 1 );
		
		unset ( $_COOKIE [$this->cookie_prefix . 'username_encode'] );
		unset ( $_COOKIE [$this->cookie_prefix . 'uid'] );
		unset ( $_COOKIE [$this->cookie_prefix . 'authcode'] );
		
		return true;
	}
}
?>